package net.pimpas.util.clone;

import java.beans.MethodDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import net.pimpas.util.reflection.ReflectionUtil;

public class CloneUtils {
	
	
	public static final Object clone(Object obj) {
		if(ReflectionUtil.isSubclass(obj.getClass(), Cloneable.class)) {
			MethodDescriptor method = ReflectionUtil.getMethodDescriptor(obj.getClass(), "clone");
			if(method != null)
				try {
					return method.getMethod().invoke(obj);
				} catch (Throwable e) {
					
				}
		}
		
		// try with clone Utils
		return (ReflectionUtil.isSubclass(obj.getClass(), Serializable.class)) ? 
				clone((Serializable) obj) : null;
	}

	public static final Serializable clone(Serializable obj){
		try{
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			ObjectOutputStream objOut = new ObjectOutputStream(out);
			objOut.writeObject(obj);
			ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
			ObjectInputStream objIn = new ObjectInputStream(in);
			return (Serializable) objIn.readObject();
		}catch(Exception ex){
			throw new RuntimeException(new CloneNotSupportedException(ex.getMessage()));
		}
	}
}